package com.pbc.gmp.commons.shiro;

import java.util.*;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.pbc.gmp.commons.utils.TreeUtils;
import com.pbc.gmp.model.LoginUserInfo;
import com.pbc.gmp.model.MenuTreeResourseDto;
import com.pbc.gmp.model.OrgTreeDto;
import com.pbc.gmp.model.basemodel.Org;
import com.pbc.gmp.model.basemodel.Position;
import com.pbc.gmp.model.basemodel.User;
import com.pbc.gmp.service.IAclService;
import com.pbc.gmp.service.IOrgService;
import com.pbc.gmp.service.IRoleService;
import com.pbc.gmp.service.IUserService;
import com.pbc.gmp.service.impl.MenuResServiceImpl;
import com.pbc.gmp.service.impl.MenuTreeService;
import com.pbc.gmp.service.impl.PositionServiceImpl;
import com.xiaoleilu.hutool.convert.Convert;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;



/**
 * @description：shiro权限认证
 * @author：zhixuan.wang
 * @date：2015/10/1 14:51
 */
public class ShiroDbRealm extends AuthorizingRealm {
    private static final Logger LOGGER = LogManager.getLogger(ShiroDbRealm.class);
    @Autowired

    private PasswordHash passwordHash;
    @Autowired private IUserService userService;
    @Autowired private IRoleService roleService;
    @Autowired private IAclService aclService;
    @Autowired private IOrgService orgService;
    @Autowired private MenuTreeService menuTreeService;
    @Autowired private MenuResServiceImpl menuResService;
    @Autowired private PositionServiceImpl positionService;
    
    public ShiroDbRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        super(cacheManager, matcher);
    }
    
    /**
     * Shiro登录认证(原理：用户提交 用户名和密码  --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 )
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        LOGGER.info("Shiro开始登录认证");
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        User uservo = new User();
        uservo.setLoginname(token.getUsername());
       //uservo = userService.selectOne(new EntityWrapper<User>(uservo));
        uservo = userService.selectUserByLoginName(token.getUsername()).get(0);
        // 账号不存在
        if (uservo == null ) {
            return null;
        }


             if (uservo.getEnabled() == 1) {
                   return null;
              }

        // 读取用户的url和角色
        Map<String, Set<String>> resourceMap = aclService.selectResourceMapByUserId(uservo.getId());
        Set<String> permissions = resourceMap.get("permissions");
        Set<String> roles = resourceMap.get("roles");
        List<OrgTreeDto> orgTreeDtos=orgService.selectAllOrg();
        Org org=orgService.selectOrgListByUserId(uservo.getId()).get(0);
        OrgTreeDto orgTree= TreeUtils.org2tree(orgTreeDtos,org.getId());
       List<MenuTreeResourseDto> menus=menuTreeService.selectLeftMenuTreeByUserId(uservo.getId());

//
//        Set<Long> roleids=new HashSet<Long>();
//        Set<MenuTreeResourseDto> menus=TreeUtils.menu2tree(menuResService.selectAllLeftMenuByRoleIds(roleids));
        List<OrgTreeDto> orgTrees=new ArrayList<OrgTreeDto>();
        orgTrees.add(orgTree);
        Position position=positionService.selectPositionByUserId(uservo.getId());
        Long positionid;String positionName;
        if(position==null)
        {
            positionid=null;
            positionName =null;
        }else {
            positionid=position.getId();
            positionName =position.getName();
        }

        LoginUserInfo shiroUser = new LoginUserInfo(uservo.getId(), uservo.getName(), uservo.getRealname(),
                uservo.getWorktitle(), uservo.getMaindepartment(),uservo.getDepartmentid(),positionid,positionName,uservo.getLoginname(), roles, permissions,orgTrees,menus);

        // 认证缓存信息
        return new SimpleAuthenticationInfo(shiroUser, uservo.getPassword().toCharArray(),
                ShiroByteSource.of(uservo.getSalt()), getName());

    }

    /**
     * Shiro权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        LoginUserInfo shiroUser = (LoginUserInfo) principals.getPrimaryPrincipal();
       SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
       info.setRoles(shiroUser.getUserRoles());
        info.addStringPermissions(shiroUser.getUserPermissions());
        return info;

    }
    
    @Override
    public void onLogout(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
       // ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();

//        System.out.println(principals.getPrimaryPrincipal().toString());
        removeUserCache(principals.getPrimaryPrincipal().toString());

       // removeUserCache(shiroUser);

    }

    /**
     * 清除用户缓存
     * @param shiroUser
     */
    public void removeUserCache(ShiroUser shiroUser){
        removeUserCache(shiroUser.getLoginName());
    }

    /**
     * 清除用户缓存
     * @param loginName
     */
    public void removeUserCache(String loginName){
        SimplePrincipalCollection principals = new SimplePrincipalCollection();
        principals.add(loginName, super.getName());
        super.clearCachedAuthenticationInfo(principals);
    }
}
